﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Compiler
{
    public class Ebnf2GrammarConvertData
    {
        private List<Production> Productions;
        private Dictionary<string, Nonterminal> MetaDict;
        private Dictionary<string, Terminal> TermDict;

        private int nextNonTerminalId = 0;
        private int nextTerminalId = 0;

        public Ebnf2GrammarConvertData()
        {
            Productions = new List<Production>();
            MetaDict = new Dictionary<string, Nonterminal>();
            TermDict = new Dictionary<string, Terminal>();
        }

        public void AddProduction(Production prod)
        {
            Productions.Add(prod);
        }

        public Grammar ConstructGrammar()
        {
            Nonterminal Start = new Nonterminal(-1, "START");
            Production pStart = new Production(-1, Start, Productions[0].Head);
            Productions.Insert(0,pStart);
            return new Grammar(Start, Productions.ToArray()); 
        }

        private int getNextNonTerminalId()
        {
            return nextNonTerminalId++;
        }

        private int getNextTerminalId()
        {
            return nextTerminalId++;
        }

        public Nonterminal GetNonterminal(string lexeme)
        {
            Nonterminal meta;
            if (!MetaDict.TryGetValue(lexeme, out meta))
            {
                meta = new Nonterminal(getNextNonTerminalId(), lexeme);
                MetaDict.Add(lexeme, meta);
            }
            return meta;
        }

        public Terminal GetTerminal(string lexeme)
        {
            Terminal term;
            if (!TermDict.TryGetValue(lexeme, out term))
            {
                term = new Terminal(getNextTerminalId(), lexeme);
                TermDict.Add(lexeme, term);
            }
            return term;
        }
    }
}
